package com.lzp.java.concurrent.buildcache;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;

/**
 * @author lzp
 * @Description: 1. 对异常进行处理，重试 2 解决缓存污染问题。
 * @date 2021/3/14
 */
public class Cache5<K, V> implements Computable<K, V> {
    private final Map<K, Future<V>> cache = new ConcurrentHashMap<>();
    private final Computable<K, V> c;

    public Cache5(Computable<K, V> c) {
        this.c = c;
    }

    @Override
    public V compute(K key) throws Exception {
        while (true) {
            Future<V> result = cache.get(key);
            if (result == null) {
                FutureTask<V> futureTask = new FutureTask<V>(() -> {
                    return c.compute(key);
                });
                result = futureTask;
                // 如果第一次缓存失败，放入的key-value是不正确的。
                result = cache.putIfAbsent(key, result);
                if (result == null) {
                    result = futureTask;
                    futureTask.run();
                }
            }
            try {
                return result.get();
            } catch (InterruptedException e) {
                cache.remove(key);
                throw e;
            } catch (ExecutionException e) {
                System.out.println("异常执行重试。。。");
                cache.remove(key); // 清除污染缓存！！
                // cache.replace() 新思路 生成一个新的任务，然后替换原来的任务。
            }
        }
    }

    public static void main(String[] args) throws Exception {
        Cache5<String, Integer> cache1 = new Cache5<>(new MayFailImpl());
        System.out.println(cache1.compute("key"));
        System.out.println(cache1.compute("key"));
    }
}
